﻿using System;
using System.Collections.Generic;
using System.Text;

//CID 0797 //2011.02.27 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
    class StringFunctions
    {
        public static string stringFunc(ExprContext context, object value)
        {
            if (value is INodeList)
            {
                INodeList nodeList = (INodeList)value;
                if (nodeList.Count <= 0)
                {
                    return "";
                }
                else
                {
                    string nodeValue = context.Calculator.GetNodeValue(nodeList.Get(0));
                    return nodeValue;
                }
            }
            else if (value is double)
            {
                double doubleValue = (double)value;
                string strValue = doubleValue.ToString("R", System.Globalization.NumberFormatInfo.InvariantInfo);
                return strValue;
            }
            else if (value is bool)
            {
                bool boolValue = (bool)value;
                if (boolValue)
                {
                    return "true";
                }
                else
                {
                    return "false";
                }
            }
            else if (value is string)
            {
                return (string)value;
            }
            else
            {
                return value.ToString();
            }
        }

        public static string concat(ExprContext context, List<object> args)
        {
            StringBuilder buffer = new StringBuilder();
            foreach (object arg in args)
            {
                string str = StringFunctions.stringFunc(context, arg);
                buffer.Append(str);
            }
            return buffer.ToString();
        }

        public static bool contains(ExprContext context, object arg1, object arg2)
        {
            string str1 = StringFunctions.stringFunc(context, arg1);
            string str2 = StringFunctions.stringFunc(context, arg2);
            if (str1.IndexOf(str2) >= 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool startsWith(ExprContext context, object arg1, object arg2)
        {
            string str1 = StringFunctions.stringFunc(context, arg1);
            string str2 = StringFunctions.stringFunc(context, arg2);
            if (str1.StartsWith(str2))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static string substringBefore(ExprContext context, object arg1, object arg2)
        {
            string str1 = StringFunctions.stringFunc(context, arg1);
            string str2 = StringFunctions.stringFunc(context, arg2);
            int index = str1.IndexOf(str2);
            if (index > 0)
            {
                return str1.Substring(0, index);
            }
            else
            {
                return "";
            }
        }

        public static string substringAfter(ExprContext context, object arg1, object arg2)
        {
            string str1 = StringFunctions.stringFunc(context, arg1);
            string str2 = StringFunctions.stringFunc(context, arg2);
            int index = str1.IndexOf(str2);
            if (index >= 0)
            {
                return str1.Substring(index + str2.Length);
            }
            else
            {
                return "";
            }
        }

        public static string substring(ExprContext context, object arg1, object arg2, object arg3)
        {
            string str = StringFunctions.stringFunc(context, arg1);
            double index = NumberFunctions.round(context, NumberFunctions.number(context, arg2));
            if (arg3 == null)
            {
                if (double.IsNaN(index))
                {
                    return "";
                }
                if (double.IsNegativeInfinity(index))
                {
                    return "";
                }
                if (index <= 0)
                {
                    return str;
                }
                if (index > str.Length)
                {
                    return "";
                }
                return str.Substring((int)index-1);
            }
            else
            {
                if (double.IsNaN(index))
                {
                    return "";
                }
                if (double.IsNegativeInfinity(index))
                {
                    return "";
                }
                double length = NumberFunctions.round(context, NumberFunctions.number(context, arg3));
                if (double.IsNaN(length))
                {
                    return "";
                }
                if (length <= 0)
                {
                    return "";
                }
                if (double.IsPositiveInfinity(length))
                {
                    return str;
                }
                double end = index + length;
                if (end <= 0)
                {
                    return "";
                }
                if (end > str.Length)
                {
                    end = str.Length + 1;
                }
                if (index <= 1)
                {
                    index = 1;
                }
                //CID 0955 //2011.06.20 //Begin
                if (str.Length < (int)index )
                {
                    return "";
                }
                //CID 0955 //2011.06.20 //End
                return str.Substring((int)index - 1, (int)((end - 1) - (index - 1)));
            }
        }

        public static double stringLength(ExprContext context, object arg)
        {
            string str = StringFunctions.stringFunc(context, arg);
            return (double)str.Length;
        }

        public static string normalizeSpace(ExprContext context, object arg)
        {
            string str = StringFunctions.stringFunc(context, arg);
            return str.Trim();
        }

        public static string translate(ExprContext context, object arg1, object arg2, object arg3)
        {
            string str1 = StringFunctions.stringFunc(context, arg1);
            string str2 = StringFunctions.stringFunc(context, arg2);
            string str3 = StringFunctions.stringFunc(context, arg3);
            char[] chars1 = str1.ToCharArray();
            char[] chars3 = str3.ToCharArray();
            StringBuilder buffer = new StringBuilder();
            foreach (char chr in chars1)
            {
                int index = str2.IndexOf(chr);
                if (index >= 0)
                {
                    if (index < chars3.Length)
                    {
                        char replacedChr = chars3[index];
                        buffer.Append(replacedChr);
                    }
                }
                else
                {
                    buffer.Append(chr);
                }
            }
            return buffer.ToString();
        }

        //CID 0796 //2011.02.26 //Begin
        public static object CallFunction(ExprContext context, string funcName, List<object> args)
        {
            if (funcName.Equals("string"))
            {
                if (args.Count == 0)
                {
                    object contextNodes = context.Calculator.GetContextNodes(false);
                    return StringFunctions.stringFunc(context, contextNodes);
                }
                else if (args.Count == 1)
                {
                    return StringFunctions.stringFunc(context, args[0]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in string().");
                }
            }
            else if (funcName.Equals("concat"))
            {
                if (args.Count >= 2)
                {
                    return StringFunctions.concat(context, args);
                }
                else
                {
                    throw new ExprException("Wrong parameters in concat().");
                }
            }
            else if (funcName.Equals("starts-with"))
            {
                if (args.Count == 2)
                {
                    return StringFunctions.startsWith(context, args[0], args[1]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in starts-with().");
                }
            }
            else if (funcName.Equals("contains"))
            {
                if (args.Count == 2)
                {
                    return StringFunctions.contains(context, args[0], args[1]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in contains().");
                }
            }
            else if (funcName.Equals("substring-before"))
            {
                if (args.Count == 2)
                {
                    return StringFunctions.substringBefore(context, args[0], args[1]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring-before().");
                }
            }
            else if (funcName.Equals("substring-after"))
            {
                if (args.Count == 2)
                {
                    return StringFunctions.substringAfter(context, args[0], args[1]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring-after().");
                }
            }
            else if (funcName.Equals("substring"))
            {
                if (args.Count == 2)
                {
                    return StringFunctions.substring(context, args[0], args[1], null);
                }
                else if (args.Count == 3)
                {
                    return StringFunctions.substring(context, args[0], args[1], args[2]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring().");
                }
            }
            else if (funcName.Equals("string-length"))
            {
                if (args.Count == 0)
                {
                    object contextNodes = context.Calculator.GetContextNodes(false);
                    return StringFunctions.stringLength(context, contextNodes);
                }
                else if (args.Count == 1)
                {
                    return StringFunctions.stringLength(context, args[0]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring().");
                }
            }
            else if (funcName.Equals("normalize-space"))
            {
                if (args.Count == 0)
                {
                    object contextNodes = context.Calculator.GetContextNodes(false);
                    return StringFunctions.normalizeSpace(context, contextNodes);
                }
                else if (args.Count == 1)
                {
                    return StringFunctions.normalizeSpace(context, args[0]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring().");
                }
            }
            else if (funcName.Equals("translate"))
            {
                if (args.Count == 3)
                {
                    return StringFunctions.translate(context, args[0], args[1], args[2]);
                }
                else
                {
                    throw new ExprException("Wrong parameters in substring().");
                }
            }
            else
            {
                return null;
            }
        }
        //CID 0796 //2011.02.28 //End
    }
}
//CID 0797 //2011.02.28 //End
